﻿/*
* CoordinateListConverter
* 
* initial implementation : 14.11.2008
*
* Copyright (c) Adam Sida, asida@centrum.cz.
* All rights reserved.
* 
* for license see Petra.Gis.License.txt
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Petra.Gis.Geometry;
using Petra.Gis.Geometry.Support;
using Petra.Gis.DataServices.WKB.Support;

namespace Petra.Gis.DataServices.WKB.Support
{
  internal static class CoordinateListConverter
  {



    internal static Geometry.Support.CoordinateList ToCoordinateList(BinaryReader mBReader/*, int arrayOffset*/, Dimension dim, WKB.ByteOrder dataEndian)
    {
      int _numPoints = 0;

      //mBReader.BaseStream.Position = arrayOffset;

      _numPoints = EndianConverter.ToInt32(mBReader.ReadInt32(), dataEndian);

      //oldschool way
      //fixed (byte* bCoordListPtr = &vData[arrayOffset])
      //{
      //  int* lNumPoints = (Int32*)bCoordListPtr;
      //  //automatic endian conversion
      //  _numPoints = EndianConverter.ToInt32(*lNumPoints, dataEndian);
      //}

      return ToCoordinateList(mBReader/*, (int)mBReader.BaseStream.Position*/, _numPoints, dim, dataEndian);

    }




    //becomes obsolette
    //internal static Geometry.Support.CoordinateList ToCoordinateList(byte[] vData, int arrayOffset, Dimension dim, WKB.ByteOrder dataEndian)
    //{
    //  int _numPoints = 0;

    //  fixed (byte* bCoordListPtr = &vData[arrayOffset])
    //  {
    //    int* lNumPoints = (Int32*)bCoordListPtr;
    //    //automatic endian conversion
    //    _numPoints = EndianConverter.ToInt32(*lNumPoints, dataEndian);
    //  }

    //  return ToCoordinateList(vData, arrayOffset + 4, _numPoints, dim, dataEndian);

    //}




    internal static Geometry.Support.CoordinateList ToCoordinateList(BinaryReader mBReader/*, int arrayOffset*/, int numOfCoords, Dimension dim, WKB.ByteOrder dataEndian)
    {

      Gis.Geometry.Support.CoordinateList Coords;

      //for big array dont process conversion automatically, ask if necessary
      if (EndianConverter.NeedEndianConversion(dataEndian))
      {
        //data are copied into new array, same effort as replace double by double in original array..
        byte[] tmp = _convertCoordArrayEndian(mBReader/*, arrayOffset*/, numOfCoords, Dimension.dim2D, dataEndian);
        Coords = new CoordinateList(tmp, 0, numOfCoords, Dimension.dim2D);
      }
      else
        Coords = new CoordinateList(((WKBMemoryStream)mBReader.BaseStream).GetBuffer(), (int)mBReader.BaseStream.Position, numOfCoords, Dimension.dim2D);

      //advance mBReader.Position
      //mBReader.BaseStream.Position = arrayOffset + (numOfCoords * (int)Coords.dimension);
      mBReader.BaseStream.Position += (numOfCoords * (int)Coords.dimension * sizeof(double));

      return Coords;

    }





    ////becomes obsolette
    //internal static Geometry.Support.CoordinateList ToCoordinateList(byte[] vData, int arrayOffset, int numOfCoords, Dimension dim, WKB.ByteOrder dataEndian)
    //{

    //  Gis.Geometry.Support.CoordinateList Coords;

    //  //for big array dont process conversion automatically, ask if necessary
    //  if (EndianConverter.NeedEndianConversion(dataEndian))
    //  {
    //    byte[] tmp = ConvertCoordArrayEndian(vData, arrayOffset, numOfCoords, Dimension.dim2D, dataEndian);
    //    Coords = new CoordinateList(tmp, 0, numOfCoords, Dimension.dim2D);
    //  }
    //  else
    //    Coords = new CoordinateList(vData, arrayOffset, numOfCoords, Dimension.dim2D);

    //  return Coords;

    //}




    private static byte[] _convertCoordArrayEndian(BinaryReader mBReader/*, int beginOfCoords*/, int numOfCoords, Dimension dim, WKB.ByteOrder dataEndian)
    {

      //byte[] coordBytes;
      System.IO.MemoryStream oIMStream = new System.IO.MemoryStream();
      System.IO.BinaryWriter mBWriter = new System.IO.BinaryWriter(oIMStream);

      //mBReader.BaseStream.Position = beginOfCoords;

      for (int i = 0; i < numOfCoords; i++)
      {
        for (int j = 0; j < (int)dim; j++)
        {
          /*coordBytes = BitConverter.GetBytes(*tmpPtr);
          Array.Reverse(coordBytes);
          mBWriter.Write(coordBytes);*/
          mBWriter.Write(EndianConverter.ToDouble(mBReader.ReadDouble(), dataEndian));
        }
      }

      return oIMStream.ToArray();

    }




    ////becomes obsolette
    // /*
    // * cordinate array contains always (double) IEEE number, aligned to its length (modulo of 8)
    // * conversion automatically treats any input array as array of double
    // */
    //  private static byte[] _convertCoordArrayEndian(byte[] coords, long beginOfCoords, int numOfCoords, Dimension dim, WKB.ByteOrder dataEndian)
    //  {

    //    //byte[] coordBytes;
    //    System.IO.MemoryStream oIMStream = new System.IO.MemoryStream();
    //    System.IO.BinaryWriter mBWriter = new System.IO.BinaryWriter(oIMStream);

    //    fixed (byte* bPtr = &coords[beginOfCoords])
    //    {

    //      double* tmpPtr = (double*)bPtr;

    //      for (int i = 0; i < numOfCoords; i++)
    //      {
    //        for (int j = 0; j < (int)dim; j++)
    //        {
    //          /*coordBytes = BitConverter.GetBytes(*tmpPtr);
    //          Array.Reverse(coordBytes);
    //          mBWriter.Write(coordBytes);*/
    //          mBWriter.Write(EndianConverter.ToDouble(*tmpPtr, dataEndian));
    //          tmpPtr++;
    //        }
    //      }
    //    }

    //    return oIMStream.ToArray();

    //  }

  }
}
